import { useBoolean } from '@gnlab/utils/env-react'
import { message, Button, Form, Input, Radio, DatePicker } from 'antd'
import dayjs, { type Dayjs } from 'dayjs'
import services from '@/services'
import type { BaseSendMomentConfig, MomentContact } from '@/services/features/send-moment'
import type { EditingConfig } from '..'
import { ChooseContacts } from './choose-contacts'
import './index.module.less'

export default function EditConfig(props: {
  config: EditingConfig
  goPrev: (editedConfig: EditingConfig) => void
  onFinish: () => void
}) {
  const { config: initialConfig, goPrev, onFinish } = props
  const [form] = Form.useForm<EditingConfig>()

  const onGoPrev = useCallback(() => {
    const values = form.getFieldsValue()
    goPrev(values)
  }, [form, goPrev])

  const [submitting, setSubmitting] = useState(false)
  const onSubmit = useCallback(
    async (values: BaseSendMomentConfig) => {
      setSubmitting(true)
      const res = await services.features.sendMoment.addOrUpdateConfig({
        id: initialConfig.id,
        ...values,
      })
      setSubmitting(false)

      if (res.success) {
        void message.success('保存成功！')
        onFinish()
      } else {
        void message.warning(`保存失败：${res.error}`)
      }
    },
    [initialConfig, onFinish],
  )

  return <Form
    styleName="form"
    form={form}
    initialValues={initialConfig}
    labelCol={{ span: 3 }}
    onFinish={onSubmit}
  >
    <Form.Item name="wxids" hidden>
      <Input />
    </Form.Item>
    <Form.Item name="content" hidden>
      <Input />
    </Form.Item>

    <Form.Item name="name" label="任务名称" rules={[{ required: true }]}>
      <Input maxLength={30} />
    </Form.Item>

    <Form.Item
      name="contacts"
      label="可见范围"
      styleName="scope-field"
      rules={getContactsRules(initialConfig.wxids)}
    >
      <ContactsInput wxids={initialConfig.wxids} />
    </Form.Item>

    <Form.Item name="sendTime" label="发布时间" styleName="send-time-field">
      <SendTimeInput />
    </Form.Item>

    <Form.Item styleName="actions">
      <Button disabled={submitting} onClick={onGoPrev}>
        上一步
      </Button>
      <Button loading={submitting} type="primary" htmlType="submit">
        完成
      </Button>
    </Form.Item>
  </Form>
}

function ContactsInput(props: {
  wxids: string[]
  value?: MomentContact[] | null
  onChange?: (value: MomentContact[] | null) => void
}) {
  const { wxids, value, onChange } = props as Required<typeof props>

  const [choosing, startChoosing, finishChoosing] = useBoolean(false)
  const onChoosed = useCallback(
    (contacts: MomentContact[]) => {
      finishChoosing()
      onChange(contacts)
    },
    [finishChoosing, onChange],
  )

  return <>
    <Radio.Group
      options={[
        { label: '全部客户', value: 'all' },
        { label: '部分客户', value: 'choose' },
      ]}
      value={value === null ? 'all' : 'choose'}
      onChange={e => onChange(e.target.value === 'all' ? null : [])}
    />
    {value && !value.length ? (
      <div>
        <a onClick={startChoosing}>选择可见的客户</a>
      </div>
    ) : null}
    {value && value.length ? (
      <div>
        <span styleName="choosed">已选择 {value.length} 个客户</span>
        <a onClick={startChoosing}>编辑</a>
      </div>
    ) : null}

    <ChooseContacts wxids={wxids} choosing={choosing ? value : null} onChoosed={onChoosed} />
  </>
}

type ContactsValue = MomentContact[] | null
function getContactsRules(configWxids: string[]) {
  return [
    {
      validator: async (_: unknown, value: ContactsValue) => contactsNotEmpty(value),
      validateTrigger: 'onSubmit',
    },
    {
      validator: async (_: unknown, value: ContactsValue) => noIdleWxids(configWxids, value),
      warningOnly: true,
    },
  ]
}
async function contactsNotEmpty(value: ContactsValue) {
  return value !== null && !value.length
    ? Promise.reject(new Error('可见客户不能为空'))
    : Promise.resolve()
}
async function noIdleWxids(configWxids: string[], value: ContactsValue) {
  if (value !== null && value.length) {
    const idleWxid = configWxids.find(wxid => !value.find(contact => contact.ownerWxid === wxid))
    if (idleWxid !== undefined)
      return Promise.reject(new Error('部分企业微信没有可见客户，它们将不会发送朋友圈'))
  }
  return Promise.resolve()
}

function SendTimeInput(props: {
  value?: number | null
  onChange?: (value: number | null) => void
}) {
  const { value, onChange } = props as Required<typeof props>

  const timeValue = useMemo(() => (value !== null ? dayjs(value * 1000) : null), [value])

  function disabledDate(current: Dayjs) {
    return current < dayjs().startOf('day')
  }
  function disabledTime(current: Dayjs | null) {
    function range(start: number, end: number) {
      const result: number[] = []
      for (let i = start; i <= end; i++) result.push(i)
      return result
    }
    return {
      disabledHours: () =>
        current && current <= dayjs().endOf('day') ? range(0, dayjs().hour() - 1) : [],
      disabledMinutes: () =>
        current && current <= dayjs().endOf('hour') ? range(0, dayjs().minute()) : [],
      disabledSeconds: () => [],
    }
  }

  return <div styleName="send-time-input">
    <Radio.Group
      value={value === null ? 'intime' : 'custom'}
      onChange={e => onChange(e.target.value === 'intime' ? null : Date.now() / 1000)}
      options={[
        { label: '立即发布', value: 'intime' },
        { label: '定时发布', value: 'custom' },
      ]}
    />
    {value !== null ? (
      <div>
        <label>选择时间：</label>
        <DatePicker
          showTime
          value={timeValue}
          onChange={timeValue => onChange(timeValue?.unix() ?? null)}
          disabledDate={disabledDate}
          disabledTime={disabledTime}
        />
      </div>
    ) : null}
  </div>
}
